package com.gitee.feizns.dynamic;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 迭代器工具类
 * @author feizns
 * @since 2022/09/11
 */
public abstract class IteratorUtils {

    /**
     * 判断迭代器中是否包含匹配条件的元素
     * @param iterator {@link Iterator}
     * @param test 测试条件
     * @param <T> {@link Iterator}
     * @return 是否包含
     */
    public static <T> boolean include(Iterator<T> iterator, Predicate<T> test) {
        return indexOf(iterator, test) != -1;
    }

    /**
     * 判断迭代器中是否包含匹配条件的元素
     * @param iterator {@link Iterator}
     * @param test 测试条件
     * @param <T> 元素
     * @return 是否包含
     */
    public static <T> boolean contains(Iterator<T> iterator, Predicate<T> test) {
        return include(iterator, test);
    }

    /**
     * 迭代器查询匹配条件元素的位置
     * @param iterator {@link Iterator}
     * @param test 测试条件
     * @param <T> 元素
     * @return 是否包含
     */
    public static <T> int indexOf(Iterator<T> iterator, Predicate<T> test) {
        int index = 0;
        while( iterator.hasNext() ) {
            if (test.test(iterator.next()))
                return index;
            index++;
        }
        return -1;
    }

    /**
     * 迭代器查询匹配条件的元素
     * @param iterator 迭代器
     * @param test {@link Predicate}
     * @return 元素
     * @param <T> 迭代器中对应索引位置上的元素
     */
    public static <T> T find(Iterator<T> iterator, Predicate<T> test) {
        while( iterator.hasNext() ) {
            T item = iterator.next();
            if ( test.test(item) )
                return item;
        }
        return null;
    }

    /**
     * 迭代器查询匹配条件元素
     * @param iterator 迭
     * @param test 接受一个元素，与元素的索引
     * @return 元素
     * @param <T> 迭代器中对应索引位置上的元素
     */
    public static <T> T index(Iterator<T> iterator, BiPredicate<T, Integer> test) {
        int index = 0;
        while( iterator.hasNext() ) {
            T item = iterator.next();
            if ( test.test(item, index++) )
                return item;
        }
        return null;
    }

    /**
     * 在迭代器中获取指定索引位置的元素
     * @param iterator {@link Iterator}
     * @param index 索引
     * @return 返回对应索引位置的元素
     * @param <T> 元素类型
     */
    public static <T> T index(Iterator<T> iterator, int index) {
        return index(iterator, (item, i) -> i.equals(index));
    }

    /**
     * 获取迭代器中第一个元素
     * @param iterator {@link Iterator}
     * @return 返回迭代器中位置第一的元素
     * @param <T> 元素类型
     */
    public static <T> T first(Iterator<T> iterator) {
        return index(iterator, 0);
    }

    /**
     * 获取迭代器中最后一个元素
     * @param iterator {@link Iterator}
     * @return 返回迭代器中最后一个元素
     * @param <T> 元素类型
     */
    public static <T> T last(Iterator<T> iterator) {
        T ret = null;
        while( iterator.hasNext() )
            ret = iterator.next();
        return ret;
    }

    /**
     * 获取迭代器中最后一个元素
     * @param iterator {@link Iterator}
     * @return 返回迭代器中最后一个元素
     * @param <T> 元素类型
     */
    public static <T> T last(ListIterator<T> iterator) {
        return iterator.hasPrevious() ? iterator.previous() : null;
    }

    /**
     * 转换为{@link List}
     * @param iterator 迭代器
     * @return {@link List}<{@link T}>
     */
    public static <T> List<T> toList(Iterator<T> iterator, Supplier<List<T>> supplier) {
        List<T> list = supplier.get();
        while ( iterator.hasNext() )
            list.add(iterator.next());
        return list;
    }

    /**
     * 转换为{@link List}
     * @param iterator 迭代器
     * @return {@link List}<{@link T}>
     */
    public static<T> List<T> toList(Iterator<T> iterator) {
        return toList(iterator, ArrayList::new);
    }

}
